package demo.practice.uf;

import java.util.HashSet;
import java.util.Set;

public class P200 {
    class UF {
        int[] parent;
        int[] rank;
        int count;

        public UF(char[][] grid) {
            count = 0;
            int h = grid.length;
            int w = grid[0].length;
            parent = new int[h * w];
            rank = new int[h * w];

            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    if (grid[i][j] == '1') {
                        //初始化,当前位置的parent  填充上值，常规套路，parent填上自己的 索引
                        parent[i * w + j] = i * w + j;
                        ++count;
                    }
                    //层数初始化，现在所有节点都是1层
                    rank[i * h + j] = 1;
                }
            }
        }

        public int find(int i) {
//            if (parent[i] != i) parent[i] = find(parent[i]);
            while (parent[i] != i)
                i = parent[i];
            return  parent[i];
        }

        public void union(int x, int y) {
            int rootx = find(x);
            int rooty = find(y);
            if (rootx != rooty) {//需要  连接合并
                if (rank[rootx] > rank[rooty]) {
                    //将层数越小的加到层数越大的上面,总体层数不变
                    parent[rooty] = rootx;
                } else if (rank[rootx] < rank[rooty]) {
                    parent[rootx] = rooty;
                } else {
                    //合并，但顶店的层数增加
                    parent[rootx] = rooty;
                    rank[rooty]++;
                }
                count--;
            }
        }

        public int getCount() {
            return count;
        }
    }


    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0) {
            return 0;
        }
        int nr = grid.length;
        int nc = grid[0].length;
        int num_islands = 0;
        UF uf = new UF(grid);
        for (int r = 0; r < nr; ++r) {
            for (int c = 0; c < nc; ++c) {
                if (grid[r][c] == '1') {
                    grid[r][c] = '0';
                    if (r - 1 >= 0 && grid[r - 1][c] == '1') {
                        uf.union(r * nc + c, (r - 1) * nc + c);
                    }
                    if (r + 1 < nr && grid[r + 1][c] == '1') {
                        uf.union(r * nc + c, (r + 1) * nc + c);
                    }
                    if (c - 1 >= 0 && grid[r][c - 1] == '1') {
                        uf.union(r * nc + c, r * nc + c - 1);
                    }
                    if (c + 1 < nc && grid[r][c + 1] == '1') {
                        uf.union(r * nc + c, r * nc + c + 1);
                    }
                }
            }
        }

        return uf.getCount();
    }


}
